import WebSocket = require("ws");
import { ReceivedData, ReceivedDataType } from "./defines";
import { Game } from "./Game";
import { PlayerData } from "./PlayerData";

const wss = new WebSocket.Server({ port: 10000 });

const playersData = new Map<WebSocket, PlayerData>();
const waitingList = new Set<WebSocket>();
const games = new Map<WebSocket, Game>();

const eventHandlers = {
  /**
   * 接受游戏开始消息
   * @param ws
   */
  [ReceivedDataType.FindGame]: (ws: WebSocket, data: any) => {
    console.log(`current waiting is: ${waitingList.size}`);
    const playerData = new PlayerData();
    playerData.name = data;
    playerData.ws = ws;
    playersData.set(ws, playerData);

    if (waitingList.size > 0) {
      for (let ws2 of waitingList) {
        const game = new Game(playersData.get(ws2), playerData);
        console.log(`game added.`);
        games.set(ws, game);
        games.set(ws2, game);
        waitingList.delete(ws2);
      }
    } else {
      waitingList.add(ws);
    }
  },
  /**
   * 接受确定消息事件
   * @param ws
   */
  [ReceivedDataType.ConfirmInit]: (ws: WebSocket) => {
    const game: Game = games.get(ws);
    game.confirmData(ws);
  },
  /**
   * 接受操作数据
   * @param ws
   */
  [ReceivedDataType.OperationData]: (ws: WebSocket, data: any) => {
    const game: Game = games.get(ws);
    game?.receiveOperationData(ws, data);
  },
};

wss.on("connection", function connection(ws: WebSocket) {
  console.log(`client in, current count: ${wss.clients.size}`);

  ws.on("message", function incoming(message: string) {
    const msg: ReceivedData = JSON.parse(message);
    // @ts-ignore
    eventHandlers[msg.type](this, msg.data);
  });

  ws.on("close", function close() {
    console.log(`closed, current count: ${wss.clients.size}`);
    const game = games.get(this);
    if (game) {
      game.gameEnd(-1);
    }
    ws.removeAllListeners();
  });

  ws.on("game-end", function () {
    console.log("client game destroy");
    games.delete(this);
    waitingList.delete(this);
  });

  ws.on("error", function error() {
    console.log("error");
    const game = games.get(this);
    if (game) {
      game.gameEnd(-1);
    }
    ws.removeAllListeners();
  });
});
